package uk.ac.ebi.uniprot.wikipedia.NotCore;

import org.apache.log4j.Logger;
import uk.ac.ebi.uniprot.wikipedia.model.GeneAccessionPair;
import uk.ac.ebi.uniprot.wikipedia.model.GeneWikiPage;
import uk.ac.ebi.uniprot.wikipedia.util.GeneWikiOrganism;
import uk.ac.ebi.uniprot.wikipedia.util.RetrievalHelper;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Set;
import java.util.TreeSet;

/**
 * Created with IntelliJ IDEA.
 * User: ljgarcia
 * Date: 02/07/12
 * Time: 14:50
 * To change this template use File | Settings | File Templates.
 */
public abstract class GeneWikiUniProtMappingRetrieval {
    private static Logger logger = Logger.getLogger(GeneWikiUniProtMappingRetrieval.class);

    protected Set<GeneAccessionPair> runMapping(Set<GeneWikiPage> set, boolean reviewed, GeneWikiOrganism organism) throws Exception {
        System.out.println(set);
        Set<GeneAccessionPair> result = new TreeSet<GeneAccessionPair>();
        StringBuilder locationBuilder = new StringBuilder("?");
        if (reviewed) {
            locationBuilder.append("reviewed:yes");
        } else {
            locationBuilder.append("reviewed:no");
        }
        if (organism.equals(GeneWikiOrganism.HUMAN)) {
            locationBuilder.append(" AND organism:" + GeneWikiOrganism.HUMAN.getOrganism());
        } else if (organism.equals(GeneWikiOrganism.MOUSE)) {
            locationBuilder.append(" AND organism:" + GeneWikiOrganism.MOUSE.getOrganism());
        }
        locationBuilder.append(" AND (");
        int i = 1;
        for (GeneWikiPage page:set)
        {
            System.out.println(page);
            locationBuilder.append("database:(type:geneid " + page.getGeneId() + ")");
            if (i == 40) { //TODO
                break;
            }
            if (i != set.size()) {
                locationBuilder.append(" OR ");
            }
            i++;

        }
        locationBuilder.append(")");

        String urlQuery = RetrievalHelper.buildQuery("UP_SEARCH_BY_GENE", URLEncoder.encode(locationBuilder.toString(), "UTF-8"));
        logger.debug("Requested URL: " + urlQuery);
        URL url = new URL(urlQuery);
        logger.info("Submitting...");
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        //HttpURLConnection.setFollowRedirects(true);
        conn.connect();

        int status = conn.getResponseCode();
        while (true)
        {
            int wait = 0;
            String header = conn.getHeaderField("Retry-After");
            if (header != null)
                wait = Integer.valueOf(header);
            if (wait == 0)
                break;
            logger.info("Waiting (" + wait + ")...");
            conn.disconnect();
            Thread.sleep(wait * 1000);
            conn = (HttpURLConnection) new URL(urlQuery).openConnection();
            conn.connect();
            status = conn.getResponseCode();
        }
        if (status == HttpURLConnection.HTTP_OK)
        {
            logger.info("Got a OK reply");

            InputStream is;
            if (conn.getResponseCode() >= 400) {
                throw new IOException("ERROR RESPONSE CODE (" + conn.getResponseCode() + ") - ");
            } else {
                is = conn.getInputStream();
            }
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
            String line;
            if ((line = reader.readLine()) != null) {
                //dismiss first line
            }
            while ((line = reader.readLine()) != null) {
                String[] split = line.split("\t");
                result.add(new GeneAccessionPair(split[1], split[0]));
            }
        } else {
            System.out.println(status + " STATUS: " + HttpURLConnection.HTTP_OK);
            logger.error("Failed, got " + conn.getResponseMessage() + " for " + urlQuery);
        }
        conn.disconnect();
        return result;
    }

    protected abstract Set<GeneAccessionPair> getMappingWithAccession() throws Exception;

    protected abstract Set<GeneAccessionPair> getMappingNoAccession() throws Exception;
}
